package com.miplus.ccrm.report.service.cti;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.miplus.ccrm.common.CmdResVo;
import com.miplus.ccrm.common.JPubUtils;
import com.miplus.ccrm.report.controller.vo.cti.*;
import com.miplus.ccrm.report.controller.vo.ivr.listAgentCallVO;
import com.miplus.ccrm.report.controller.vo.rep.*;
import com.miplus.ccrm.report.controller.vo.robot.CallStatsVo;
import com.miplus.ccrm.report.feign.FiImpAddVo;
import com.miplus.ccrm.report.feign.ICoreFeign;
import com.miplus.ccrm.report.pojo.ReportCallHist;
import com.miplus.ccrm.report.service.ExportService;
import com.miplus.ccrm.report.mapper.ReportCallHistMapper;
import com.miplus.ccrm.report.utils.SpringContextUtil;
import com.miplus.ccrm.report.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author pc
* @description 针对表【report_call_hist】的数据库操作Service实现
* @createDate 2024-07-30 13:27:08
*/
@Service
@Slf4j
public class ReportCallHistServiceImpl extends ServiceImpl<ReportCallHistMapper, ReportCallHist>
    implements ReportCallHistService {
    @Resource
    private ExportService exportService;
    @Resource
    private ICoreFeign iCoreFeign;
    @Resource
    private AspectReportService aspectReportService;

    @Override
    public IPage<CallAgDayResVo> repAgentCallDay(String usrid, CallAgDayReqVo paras) {
        return baseMapper.repAgentCallDay(new Page<>(paras.getPageNum(), paras.getPageSize()), usrid, paras);
    }

    @Override
    public IPage<RecyAgDayResVo> recoveryTotal(String usrid, RecyAgDayReqVo paras) {
        return baseMapper.recoveryTotal(new Page<>(paras.getPageNum(), paras.getPageSize()), usrid, paras);
    }

    @Override
    public IPage<DistCaseNumResVo> assignTotal(String usrid, DistCaseNumReqVo paras) {
        return baseMapper.assignTotal(new Page<>(paras.getPageNum(), paras.getPageSize()), usrid, paras);
    }

    @Override
    public CmdResVo expAgentCallDay(String usrid, CallAgDayReqVo paras, HttpServletResponse response) {
        IPage<CallAgDayResVo> pages = repAgentCallDay(usrid, paras);
        ArrayList arr = new ArrayList();

        String exptempid = JPubUtils.getExpTempID(paras.getExpfilename(), "坐席呼叫统计日报");
        String filename = JPubUtils.getExpFileName(
                paras.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                usrid
        );

        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
            String token = SpringContextUtil.getBearerToken();
            iCoreFeign.addImportHist(addVo, token);
        }
        arr.clear();

        return resVo;
    }

    @Override
    public CmdResVo expRecoveryTotal(String usrid, RecyAgDayReqVo paras, HttpServletResponse response) {
        IPage<RecyAgDayResVo> pages = recoveryTotal(usrid, paras);
        ArrayList arr = new ArrayList();

        String exptempid = JPubUtils.getExpTempID(paras.getExpfilename(), "回收表现统计表");
        String filename = JPubUtils.getExpFileName(
                paras.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                usrid
        );

        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
            String token = SpringContextUtil.getBearerToken();
            iCoreFeign.addImportHist(addVo, token);
        }
        arr.clear();

        return resVo;
    }

    @Override
    public CmdResVo expAssignTotal(String usrid, DistCaseNumReqVo paras, HttpServletResponse response) {
        IPage<DistCaseNumResVo> pages = assignTotal(usrid, paras);
        ArrayList arr = new ArrayList();

        String exptempid = JPubUtils.getExpTempID(paras.getExpfilename(), "分配案件数量统计表");
        String filename = JPubUtils.getExpFileName(
                paras.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                usrid
        );

        return resVo;
    }

    /**
     * 统计机器的日报
     *
     * @param paras
     * @return
     */
    @Override
    public IPage<CallStatsVo> repRobotCallDay(CallStatsReqVo paras) {
        return baseMapper.repRobotCallDay(new Page<>(paras.getPageNum(), paras.getPageSize()), paras);
    }

    @Override
    public IPage<listAgentCallVO> listAgentCall(listAgReqCallVo paras) {
        return baseMapper.listAgentCall(new Page<>(paras.getPageNum(), paras.getPageSize()), paras);
    }

    /**
     * 导出机器人日报
     *
     * @param paras
     * @param response
     * @return
     */
    @Override
    public CmdResVo expRobotCallDay(CallStatsReqVo paras, HttpServletResponse response) {
        IPage<CallStatsVo> pages = repRobotCallDay(paras);
        ArrayList arr = new ArrayList();
        String exptempid = JPubUtils.getExpTempID(paras.getExpfilename(), "机器人呼叫统计日报");
        String filename = JPubUtils.getExpFileName(
                paras.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                "robotai"
        );
        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
        }
        arr.clear();

        return resVo;
    }

    /**
     * 呼叫明细导出
     *
     * @param paras
     * @param response
     * @return
     */
    @Override
    public CmdResVo expReportCallList(listAgReqCallVo paras, HttpServletResponse response) {
        IPage<listAgentCallVO> pages = listAgentCall(paras);
        ArrayList arr = new ArrayList();
        String exptempid = JPubUtils.getExpTempID(paras.getExpfilename(), "呼叫明细表");
        String filename = JPubUtils.getExpFileName(
                paras.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                "agent"
        );
        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
        }
        arr.clear();

        return resVo;
    }

    @Override
    public IPage<AcdResVo> repAcdCallDay(AcdReqVo paras) {
        return baseMapper.repAcdCallDay(new Page<>(paras.getPageNum(), paras.getPageSize()), paras);
    }

    @Override
    public CmdResVo expAcdCallDay(AcdReqVo paras, HttpServletResponse response) {
        IPage<AcdResVo> pages = repAcdCallDay(paras);
        ArrayList arr = new ArrayList();
        String exptempid = JPubUtils.getExpTempID(paras.getExpfilename(), "Acd统计日表");
        String filename = JPubUtils.getExpFileName(
                paras.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                paras.getExpidlist(),
                paras.getExpnamelist(),
                filename,
                "acd"
        );
        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
        }
        arr.clear();

        return resVo;
    }

    @Override
    public IPage<CallStatisticsResVo> repCallStatistics(CallStatisticsReqVo paras) {
        return baseMapper.repCallStatistics(new Page<>(paras.getPageNum(), paras.getPageSize()), paras);
    }

    @Override
    public CmdResVo expCallStatistics(CallStatisticsReqVo callStatisticsReqVo, HttpServletResponse response) {
        IPage<CallStatisticsResVo> pages = repCallStatistics(callStatisticsReqVo);
        ArrayList arr = new ArrayList();
        String exptempid = JPubUtils.getExpTempID(callStatisticsReqVo.getExpfilename(), "通话统计报表");
        String filename = JPubUtils.getExpFileName(
                callStatisticsReqVo.getExpfilename(), exptempid
        );
        pages.convert(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
            return u;
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                callStatisticsReqVo.getExpidlist(),
                callStatisticsReqVo.getExpnamelist(),
                filename,
                "callstatistics"
        );
        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
        }
        arr.clear();
        return resVo;
    }

    /**
     * 统计指定时间段内各归属地的手机号数量
     */
//    @Override
//    public IPage<AreaStatisticResVo> statisticsByTimeRange(AreaStatisticReqVo paras) {
//        // 记录总耗时
//        long totalStartTime = System.currentTimeMillis();
//        try {
//            Date startTime = paras.getStartTime();
//            Date endTime = paras.getEndTime();
//
//            // 处理空时间参数
//            if (startTime == null) {
//                startTime = DateUtil.offsetDay(new Date(), -7);
//            }
//            if (endTime == null) {
//                endTime = new Date();
//            }
//
//            // 1. 数据库查询耗时统计
//            long dbQueryStart = System.currentTimeMillis();
//            QueryWrapper<ReportCallHist> queryWrapper = new QueryWrapper<>();
//            queryWrapper.between("STARTDATETIME", startTime, endTime)
//                    .in("CALLTYPE", "0", "1")
//                    .isNotNull("STARTDATETIME")
//                    .select("CALLMANAGENUMBER", "ANI", "STARTDATETIME");
//
//            List<ReportCallHist> callRecords = baseMapper.selectList(queryWrapper);
//            long dbQueryEnd = System.currentTimeMillis();
//            log.info("数据库查询完成，返回记录数:{}，耗时:{}ms",
//                    callRecords.size(), dbQueryEnd - dbQueryStart);
//
//            // 2. 内存去重耗时统计
//            long distinctStart = System.currentTimeMillis();
//            Map<String, ReportCallHist> uniqueCallMap = callRecords.stream()
//                    .collect(Collectors.toMap(
//                            record -> DateUtil.format(record.getStartdatetime(), "yyyy-MM-dd")
//                                    + "_" + record.getCallmanagenumber()
//                                    + "_" + record.getAni(),
//                            record -> record,
//                            (existing, replacement) -> existing
//                    ));
//            long distinctEnd = System.currentTimeMillis();
//            log.info("内存去重完成，去重后记录数:{}，耗时:{}ms",
//                    uniqueCallMap.size(), distinctEnd - distinctStart);
//
//            // 3. 批量获取归属地耗时统计
//            long areaQueryStart = System.currentTimeMillis();
//            Set<String> phoneNumbers = uniqueCallMap.values().stream()
//                    .map(ReportCallHist::getAni)
//                    .collect(Collectors.toSet());
//            Map<String, String> phoneAreaMap = aspectReportService.getPhoneAreas(phoneNumbers);
//            long areaQueryEnd = System.currentTimeMillis();
//            log.info("批量获取归属地完成，手机号数量:{}，耗时:{}ms",
//                    phoneNumbers.size(), areaQueryEnd - areaQueryStart);
//
//            // 4. 分组统计耗时统计
//            long groupStart = System.currentTimeMillis();
//            Map<String, Long> dateAreaCountMap = uniqueCallMap.values().stream()
//                    .collect(Collectors.groupingBy(
//                            record -> {
//                                String date = DateUtil.format(record.getStartdatetime(), "yyyy-MM-dd");
//                                String area = phoneAreaMap.getOrDefault(record.getAni(), "未知");
//                                return date + "_" + area;
//                            },
//                            Collectors.counting()
//                    ));
//            long groupEnd = System.currentTimeMillis();
//            log.info("分组统计完成，统计组数:{}，耗时:{}ms",
//                    dateAreaCountMap.size(), groupEnd - groupStart);
//
//            // 5. 区域筛选耗时统计
//            long filterStart = System.currentTimeMillis();
//            if (StringUtils.hasText(paras.getAreaName())) {
//                dateAreaCountMap.entrySet().removeIf(
//                        entry -> !entry.getKey().contains(paras.getAreaName())
//                );
//            }
//            long filterEnd = System.currentTimeMillis();
//            log.info("区域筛选完成，筛选后组数:{}，耗时:{}ms",
//                    dateAreaCountMap.size(), filterEnd - filterStart);
//
//            // 6. 转换与排序耗时统计
//            long convertSortStart = System.currentTimeMillis();
//            List<AreaStatisticResVo> resVoList = dateAreaCountMap.entrySet().stream()
//                    .map(entry -> {
//                        String[] keyParts = entry.getKey().split("_", 2);
//                        AreaStatisticResVo resVo = new AreaStatisticResVo();
//                        resVo.setCrdt(keyParts[0]);
//                        resVo.setAreaName(keyParts[1]);
//                        resVo.setCount(entry.getValue());
//                        return resVo;
//                    })
//                    .sorted((v1, v2) -> {
//                        int dateCompare = v2.getCrdt().compareTo(v1.getCrdt());
//                        return dateCompare != 0 ? dateCompare : v2.getCount().compareTo(v1.getCount());
//                    })
//                    .collect(Collectors.toList());
//            long convertSortEnd = System.currentTimeMillis();
//            log.info("转换与排序完成，结果数:{}，耗时:{}ms",
//                    resVoList.size(), convertSortEnd - convertSortStart);
//
//            // 7. 分页处理耗时统计
//            long pageStart = System.currentTimeMillis();
//            int pageNum = paras.getPageNum();
//            int pageSize = paras.getPageSize();
//            int total = resVoList.size();
//            int startIndex = PageUtil.getStart(pageNum - 1, pageSize);
//            int endIndex = Math.min(startIndex + pageSize, total);
//            List<AreaStatisticResVo> pageList = startIndex < total ?
//                    resVoList.subList(startIndex, endIndex) :
//                    Collections.emptyList();
//
//            Page<AreaStatisticResVo> page = new Page<>(pageNum, pageSize);
//            page.setTotal(total);
//            page.setRecords(pageList);
//            long pageEnd = System.currentTimeMillis();
//            log.info("分页处理完成，当前页记录数:{}，耗时:{}ms",
//                    pageList.size(), pageEnd - pageStart);
//
//            // 总耗时统计
//            long totalEndTime = System.currentTimeMillis();
//            log.info("统计归属地通话次数总耗时:{}ms", totalEndTime - totalStartTime);
//
//            return page;
//
//        } catch (Exception e) {
//            log.error("统计归属地通话次数失败，总耗时:{}ms",
//                    System.currentTimeMillis() - totalStartTime, e);
//            return new Page<>();
//        }
//    }
    public IPage<AreaStatisticResVo> statisticsByTimeRange(AreaStatisticReqVo paras) {
        // 记录总耗时
        long totalStartTime = System.currentTimeMillis();
        try {
//            // 1. 数据库查询耗时统计
            long fullQueryStart = System.currentTimeMillis();
            List<ReportCallHist> callRecords = baseMapper.selectDistinctRecords(paras.getStartDate(), paras.getEndDate());
            long fullQueryEnd = System.currentTimeMillis();
            log.info("查询+结果映射总耗时:{}ms", fullQueryEnd - fullQueryStart);
            // 2. 内存二次去重（双重保障）
            long distinctStart = System.currentTimeMillis();
            Map<String, ReportCallHist> uniqueCallMap = callRecords.stream()
                    .filter(record -> StringUtils.hasText(record.getCallmanagenumber()))
                    .filter(record -> StringUtils.hasText(record.getAni()))
                    .collect(Collectors.toMap(
                            ReportCallHist::getCallmanagenumber,
                            record -> record,
                            (existing, replacement) -> existing
                    ));
            long distinctEnd = System.currentTimeMillis();
            log.info("内存二次去重完成，去重后记录数:{}，耗时:{}ms",
                    uniqueCallMap.size(), distinctEnd - distinctStart);

            // 3. 批量获取归属地
            long areaQueryStart = System.currentTimeMillis();
            Set<String> phoneNumbers = uniqueCallMap.values().stream()
                    .map(ReportCallHist::getAni)
                    .collect(Collectors.toSet());

            Map<String, String> phoneAreaMap;
            if (!phoneNumbers.isEmpty()) {
                phoneAreaMap = aspectReportService.getPhoneAreas(phoneNumbers);
            } else {
                phoneAreaMap = Collections.emptyMap();
            }
            long areaQueryEnd = System.currentTimeMillis();
            log.info("批量获取归属地完成，手机号数量:{}，耗时:{}ms",
                    phoneNumbers.size(), areaQueryEnd - areaQueryStart);

            // 4. 按区域分组统计
            long groupStart = System.currentTimeMillis();
            Map<String, Long> areaCountMap = uniqueCallMap.values().stream()
                    .collect(Collectors.groupingBy(
                            record -> phoneAreaMap.getOrDefault(record.getAni(), "未知"),
                            Collectors.counting()
                    ));
            long groupEnd = System.currentTimeMillis();
            log.info("分组统计完成，统计组数:{}，耗时:{}ms",
                    areaCountMap.size(), groupEnd - groupStart);
            // 5. 区域筛选
            long filterStart = System.currentTimeMillis();
            if (StringUtils.hasText(paras.getAreaName())) {
                String areaName = paras.getAreaName().trim();
                areaCountMap.entrySet().removeIf(
                        entry -> !entry.getKey().contains(areaName)
                );
            }
            long filterEnd = System.currentTimeMillis();
            log.info("区域筛选完成，筛选后组数:{}，耗时:{}ms",
                    areaCountMap.size(), filterEnd - filterStart);
            // 6. 转换与排序
            long convertSortStart = System.currentTimeMillis();
            List<AreaStatisticResVo> resVoList = areaCountMap.entrySet().stream()
                    .map(entry -> {
                        AreaStatisticResVo resVo = new AreaStatisticResVo();
                        resVo.setAreaName(entry.getKey());
                        resVo.setCount(entry.getValue());
                        return resVo;
                    })
                    .sorted((v1, v2) -> v2.getCount().compareTo(v1.getCount()))
                    .collect(Collectors.toList());
            long convertSortEnd = System.currentTimeMillis();
            log.info("转换与排序完成，结果数:{}，耗时:{}ms",
                    resVoList.size(), convertSortEnd - convertSortStart);
            // 7. 手动分页（针对统计结果分页，合理且高效）
            long pageStart = System.currentTimeMillis();
            int pageNum = paras.getPageNum() == null ? 1 : paras.getPageNum();
            int pageSize = paras.getPageSize() == null ? 10 : paras.getPageSize();
            int total = resVoList.size();
            int startIndex = (pageNum - 1) * pageSize;
            int endIndex = Math.min(startIndex + pageSize, total);
            List<AreaStatisticResVo> pageList;
            if (startIndex >= total) {
                pageList = Collections.emptyList();
            } else {
                pageList = resVoList.subList(startIndex, endIndex);
            }
            Page<AreaStatisticResVo> page = new Page<>(pageNum, pageSize);
            page.setTotal(total);
            page.setRecords(pageList);
            long pageEnd = System.currentTimeMillis();
            log.info("分页处理完成，当前页记录数:{}，耗时:{}ms",
                    pageList.size(), pageEnd - pageStart);
            // 总耗时统计
            long totalEndTime = System.currentTimeMillis();
            log.info("统计归属地总数总耗时:{}ms", totalEndTime - totalStartTime);
            return page;
        } catch (Exception e) {
            log.error("统计归属地总数失败，总耗时:{}ms",
                    System.currentTimeMillis() - totalStartTime, e);
            return new Page<>();
        }
    }

    @Override
    public List<CallInTrendResVo> queryCallInTrend(CallInTrendReqVo paras) {
        return baseMapper.queryCallInTrend(paras);
    }

    @Override
    public CmdResVo expCallInTrend(CallInTrendReqVo callInTrendReqVo, HttpServletResponse response) {
        List<CallInTrendResVo> pages = queryCallInTrend(callInTrendReqVo);
        ArrayList arr = new ArrayList();
        String exptempid = JPubUtils.getExpTempID(callInTrendReqVo.getExpfilename(), "通话趋势报表");
        String filename = JPubUtils.getExpFileName(
                callInTrendReqVo.getExpfilename(), exptempid
        );
        pages.forEach(u -> {
            HashMap map = JPubUtils.toExportMap(u);
            if (map != null) arr.add(map);
        });
        CmdResVo resVo = exportService.ToExcel(
                response,
                arr,
                callInTrendReqVo.getExpidlist(),
                callInTrendReqVo.getExpnamelist(),
                filename,
                "callintrend"
        );
        int okcount = resVo.getCount();
        if (okcount > 0) {
            FiImpAddVo addVo = new FiImpAddVo();
            addVo.setBatchid(resVo.getKeyId());
            addVo.setFilename(filename);
            addVo.setTempid(exptempid);
            addVo.setOkcount(okcount);
        }
        arr.clear();
        return resVo;
    }


}



